package com.zaydanwu.cla.model.result;

import lombok.Getter;
import lombok.Setter;

import java.io.Serializable;
import java.util.Collections;

/**
 * @author wzo
 * @since 2.0.0 2018-12-13
 */
@Setter
@Getter
public class ApiResult<T> implements Serializable {

    /**
     * http响应体：成功
     */
    private static final ApiResult SUCCESS_RESULT = success(Collections.emptyMap());

    /**
     * http响应体：成功，无数据
     */
    private static final ApiResult EMPTY_SUCCESS_RESULT = success((Object) null);

    /**
     * 结果是否成功
     */
    private boolean success;

    /**
     * 错误码
     * 可以是api:argument.illegal这种类型，也可以是8位数字的类型，由具体应用来决定
     */
    // 最好字段名为code，更精简，但减少前端的转换工作及兼容性，保持与电税、信息部一致，使用messageCode
    private String messageCode;

    /**
     * 错误信息
     */
    private String message;

    /**
     * 处理结果，根据具体接口来决定。
     * 定义成泛型，有利于在java端从json反序列化的时候，直接映射成所需要的对象。
     * <p>注：在有错误的时候，这个值一定要设置成null，一可以减少返回字节数，二是在反序列时不会因为类型对不上，而导致出错
     */
    private T data;

    public ApiResult() {
    }

    public ApiResult(boolean success, String messageCode, String message, T data) {
        this.success = success;
        this.messageCode = messageCode;
        this.message = message;
        this.data = data;
    }

    /**
     * 返回成功处理结果
     */
    public static <T> ApiResult<T> success() {
        return SUCCESS_RESULT;
    }

    /**
     * 返回无data结点的成功数据
     *
     * @since 1.3.0
     */
    public static <T> ApiResult<T> empty() {
        return EMPTY_SUCCESS_RESULT;
    }

    /**
     * 根据给定的数据返回成功处理结果
     *
     * @param data 业务数据体
     */
    public static <T> ApiResult<T> success(T data) {
        return new ApiResult<T>(true, null, null, data);
    }

    /**
     * 在某些特殊场景下，在返回成功的情况下，也需要错误码
     *
     * @param data    业务数据体
     * @param code    错误码
     * @param message 错误信息
     * @since 1.3.0
     */
    public static <T> ApiResult<T> success(T data, String code, String message) {
        return new ApiResult<T>(true, code, message, data);
    }

    /**
     * 返回错误的结果处理对象
     *
     * @param code    错误码
     * @param message 错误描述信息
     */
    public static <T> ApiResult<T> failure(String code, String message) {
        return new ApiResult<T>(false, code, message, null);
    }

}
